fn test1() {
    // all have type `Option<i32>`
    let number = Some(7);
    let letter: Option<i32> = None;
    let emoticon: Option<i32> = None;

    // the `if let` construct reads: "if `let` destructures `number` into
    // `Some(i)`, evaluate the block (`{}`)".
    if let Some(i) = number {
        println!("Matched {:?}", i);
    }

    // we can't use the variable `i` outside of the if block
    // if we cancel the comment of the following statement, compiler will report error: cannot find value `i` in this scope
    // println!("i is :{}", i);

    // if you need to specify a failure, use an else.
    if let Some(i) = letter {
        println!("Matched {:?}", i);
    } else {
        // Destructure failed. change to the failure case.
        println!("Didn't match a number. Let's go with a letter!");
    }

    // provide an altered failing condition
    let i_like_letters = false;

    if let Some(i) = emoticon {
        println!("Matched {:?}!", i);
        // Destructure failed. Evaluate an `else if` condition to see if the
        // alternate failure branch should be taken:
    } else if i_like_letters {
        println!("Didn't match a number. Let's go with a letter!");
    } else {
        // the condition evaluated false. thie branch is the default:
        println!("I don't like letters. Let's go with an emoticon :)!");
    }
}

fn test2() {
    enum Foo {
        Bar,
        Baz,
        Qux(u32),
    }

    let a = Foo::Bar;
    let b = Foo::Baz;
    let c = Foo::Qux(100);

    // Variable a matches Foo::Bar
    if let Foo::Bar = a {
        println!("a is Foo::Bar");
    }

    // Variable b does not match Foo::Bar
    // so this will print nothing
    if let Foo::Bar = b {
        println!("b is Foo::Bar");
    }

    // Variable c matches Foo::Qux which has a value
    // similar to Some() in the previous example
    if let Foo::Qux(value) = c {
        println!("c is {}", value);
    }

    // Binding alse works with `if let`
    if let Foo::Qux(value@1..=100) = c {
        println!("c is :{}", value);
    }
}

fn main() {
    test1();
    test2();
}